#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Mikan Application Error

Mikan Python Web Framework
"""

__author__ = "K.Sonohara"
__status__ = "develop"
__version__ = "0.0.0_38"
__date__    = "2014/02/09"
__license__ = 'LGPL'

# ------------------------------------------------------------
## インポート
# ------------------------------------------------------------
# Python
import traceback

# ESiPC
from esipc import ESiPCProperty

# Mikan
from mikan.app import MikanApp
from mikan.core import MIKAN_CONTENT_TYPE, MIKAN_HTTP_HEADER, MIKAN_INI, MIKAN_HTTP_STATUS
from mikan.exception import AbstractMikanException, AbstractMikanStatusException
from mikan.util import get_traceback_exc

# ------------------------------------------------------------
## 変数
# ------------------------------------------------------------

# ------------------------------------------------------------
## 関数
# ------------------------------------------------------------

# ------------------------------------------------------------
## クラス
# ------------------------------------------------------------

# ------------------------------------------------------------
## Mikan エラー アプリケーション クラス
#
class AbstractMikanErrorApp(MikanApp):

	# ----------------------------------------------------
	## HTTPコード フィールドゲッター
	# @return 取得した値
	def get_status(self):
		return self.FStatus

	# ----------------------------------------------------
	## メッセージ フィールドゲッター
	# @return 取得した値
	def get_message(self):
		return self.FMessage

	# ----------------------------------------------------
	## 例外 フィールドゲッター
	# @return 取得した値
	def get_exception(self):
		return self.FException

	# ----------------------------------------------------
	## コンストラクタ
	#  @param request リクエスト
	#  @param message メッセージ
	#  @param exception 例外
	def __init__(self, request, status=500, message=None, exception=None):
		# 継承元処理
		super(AbstractMikanErrorApp, self).__init__(request)

		# 値の設定
		self.FException = exception
		s = status
		m = message
		if exception != None:
			if isinstance(exception, AbstractMikanStatusException):
				s = exception.status
			if isinstance(exception, AbstractMikanException):
				m = exception.message
		self.FStatus = s
		self.FMessage = m

		# 処理
		self.perform()

	# ----------------------------------------------------
	## 処理
	# @return Trueなら続行
	def perform(self):
		# 認証エラー
		if (self.status == MIKAN_HTTP_STATUS.STATUS_UNAUTHORIZED):
			# 認証メッセージ
			r = self.request.get_config_value(MIKAN_INI.SITE, MIKAN_INI.REALM, MIKAN_HTTP_HEADER.DEFAULT_WWW_AUTHENTICATE)

			# ログ
			if self.islogdebug:
				self.logger.debug(r)

			# HTTPヘッダーに設定
			self.request.headers[MIKAN_HTTP_HEADER.NAME_WWW_AUTHENTICATE] = MIKAN_HTTP_HEADER.VALUE_WWW_AUTHENTICATE % (r)

		# SendRedirect
		if (self.status == MIKAN_HTTP_STATUS.STATUS_MOVEDPERMANENTLY):
			url = self.exception.url

			# HTTPヘッダーに設定
			self.request.headers[MIKAN_HTTP_HEADER.NAME_LOCATION] = str(url)
			self.request.headers[MIKAN_HTTP_HEADER.NAME_CACHE_CONTROL] = MIKAN_HTTP_HEADER.VALUE_CACHE_CONTROL
			self.request.headers[MIKAN_HTTP_HEADER.NAME_PRAGMA] = MIKAN_HTTP_HEADER.VALUE_PRAGMA
			self.request.headers[MIKAN_HTTP_HEADER.NAME_EXPIRES] = MIKAN_HTTP_HEADER.VALUE_EXPIRES_NONE

		# ログ
		if self.islogdebug:
			self.logger.debug(self.status)
			self.logger.debug(self.message)

		# 指定メッセージがある場合
		if (self.message != None):
			message = self.message
		# 指定メッセージが無い場合
		else:
			message = MIKAN_HTTP_STATUS.CODES[self.status]

		# 処理結果
		self.request.status = self.status
		self.request.contenttype = MIKAN_CONTENT_TYPE.TEXT_PLAIN

		# メッセージ設定
		exception = None
		if self.islogdebug:
			exception = self.exception
		self.perform_content(message, exception)

		# 処理結果
		return True

	def perform_content(self, message, exception):
		pass

	def is_debug_traceback(self):
		if self.islogdebug:
			return True

		try:
			if self.request.httphost.index("localhost") == 0:
				return True
		except:
			pass

		return False

	def debug_traceback(self, exception, text):
		# エラーの場合
		if self.is_debug_traceback():
			iserror = True
			if self.request.status == MIKAN_HTTP_STATUS.STATUS_NOT_FOUND:
				iserror = False
			elif self.request.status == MIKAN_HTTP_STATUS.STATUS_MOVEDPERMANENTLY:
				iserror = False
			elif self.request.status == MIKAN_HTTP_STATUS.STATUS_UNAUTHORIZED:
				iserror = False

			if iserror:
				# トレース
				tb =get_traceback_exc()
				try:
					return text % tb
				except:
					pass

				# ログ出力
				try:
					self.logger.error(tb)
				except:
					pass
		return ""

	# ----------------------------------------------------
	## Property
	status = ESiPCProperty(get_status, None, None)
	message = ESiPCProperty(get_message, None, None)
	exception = ESiPCProperty(get_exception, None, None)

# ------------------------------------------------------------
## Mikan エラー アプリケーション クラス
#
class MikanErrorApp(AbstractMikanErrorApp):

	# ----------------------------------------------------
	## コンストラクタ
	#  @param request リクエスト
	#  @param message メッセージ
	#  @param exception 例外
	def __init__(self, request, status=500, message=None, exception=None):
		# 継承元処理
		super(MikanErrorApp, self).__init__(request, status, message, exception)

	def perform_content(self, message, exception):
		# 処理結果
		self.request.status = self.status
		self.request.contenttype = MIKAN_CONTENT_TYPE.TEXT_PLAIN

		# メッセージ
		m = u"%d: %s" % (self.status, message)

		# デバッグ情報
		if self.is_debug_traceback():
			debug = self.debug_traceback(exception, u"%s")
			m = u"%s\n\n-------------------------------------------------------------\n%s\n-------------------------------------------------------------\n" % (m, self.exception)
			m = u"%s%s" % (m, debug)

		# メッセージ設定
		self.request.content = str(m.encode("utf-8"))

# ------------------------------------------------------------
## Mikan エラー アプリケーション クラス
#
class MikanHTMLErrorApp(AbstractMikanErrorApp):

	# ----------------------------------------------------
	## コンストラクタ
	#  @param request リクエスト
	#  @param message メッセージ
	#  @param exception 例外
	def __init__(self, request, status=500, message=None, exception=None):
		# 継承元処理
		super(MikanHTMLErrorApp, self).__init__(request, status, message, exception)

	def perform_content(self, message, exception):
		m = message
		if m:
			m = unicode(message)
		else:
			m = u""

		# 処理結果
		self.request.status = self.status
		self.request.contenttype = MIKAN_CONTENT_TYPE.TEXT_HTML

		# デバッグ情報
		debug = self.debug_traceback(exception, u"<hr /><pre>%s</pre>")

		# サーバ情報
		soft = ""
		try:
			soft = unicode(self.request.serversoftware)
		except:
			pass

		# メッセージ
		html = u"""<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>%d %s</title>
</head>
<body>
<h1>%s</h1>
<p>%d: %s</p>
%s
<hr />
<b>%s</b>
</body></html>
""" % (self.status, message, message, self.status, MIKAN_HTTP_STATUS.CODES[self.status], debug, soft)

		# メッセージ設定
		self.request.content = str(html.encode("utf-8"))

# ------------------------------------------------------------
## メイン関数
# ------------------------------------------------------------
if __name__ == '__main__':
	pass

# ------------------------------------------------------------
